﻿// -------------------------------------------------------------------------
//    @FileName         :    NFPlayerUtil.h
//    @Author           :    gaoyi
//    @Date             :    24-8-13
//    @Email            :    445267987@qq.com
//    @Module           :    NFPlayerUtil
//
// -------------------------------------------------------------------------

#pragma once

#include <NFLogicCommon/NFBaseDefine.h>

#include "proto_cs_login.pb.h"
#include "NFComm/NFCore/NFPlatform.h"

namespace proto_ff
{
    class tbRoleDetail;
}

struct RoleOne;
class NFPlayer;
class NFSession;

class NFPlayerUtil
{
public:
    static int Tick();

public:
    /// 根据全局ID获取玩家对象
    /// @param iGlobalID 玩家的全局ID
    /// @return 返回对应的玩家对象，如果找不到则返回空指针
    static NFPlayer* GetPlayer(int iGlobalID, bool bPrintTraceStack = true,  TagGetPlayerType enType = GET_PLAYER_ANY);

    /// 根据全局ID获取活跃玩家对象
    /// @param iGlobalID 玩家的全局ID
    /// @return 返回对应的活跃玩家对象，如果找不到则返回空指针
    static NFPlayer* GetActivePlayer(int iGlobalID, bool bPrintTraceStack = true);

    /// 根据角色ID获取玩家对象
    /// @param ullRoleID 玩家的角色ID
    /// @return 返回对应的角色ID的玩家对象，如果找不到则返回空指针
    static NFPlayer* GetPlayerByRoleID(uint64_t ullRoleID);

    /// 根据角色ID获取活跃玩家对象
    /// @param ullRoleID 玩家的角色ID
    /// @return 返回对应的角色ID的活跃玩家对象，如果找不到则返回空指针
    static NFPlayer* GetActivePlayerByRoleID(uint64_t ullRoleID);
public:
    /**
     * 登录玩家
     *
     * @param pPlayer 指向玩家对象的指针
     * @param iIsResume 是否恢复游戏的标志
     * @return 返回登录操作的结果
     */
    static int LoginPlayer(NFPlayer* pPlayer, bool iIsResume);

    /**
     * 注销玩家
     *
     * @param pPlayer 指向玩家对象的指针
     * @return 返回注销操作的结果
     */
    static int LogoutPlayer(NFPlayer* pPlayer);

    /**
     * @brief 断开与指定玩家的连接
     *
     * 该函数用于断开与指定玩家的连接，并根据提供的类型和原因执行相应的操作。
     * 通常用于处理玩家主动断开连接或服务器强制断开连接的情况。
     *
     * @param pPlayer 指向NFPlayer对象的指针，表示要断开连接的玩家。
     * @param iType 断开连接的类型，用于区分不同的断开场景（如正常断开、超时断开等）。
     * @param iReason 断开连接的原因，用于记录或显示断开连接的具体原因。
     *
     * @return 返回一个整数值，表示断开连接操作的结果。通常返回0表示成功，非0值表示失败或错误代码。
     */
    static int DisconnectPlayer(NFPlayer *pPlayer, int iType, int iReason);

    /**
     * 删除玩家
     *
     * @param pPlayer 指向玩家对象的指针
     * @return 返回删除操作的结果
     */
    static int DeletePlayer(NFPlayer* pPlayer);

    // 从服务器中踢出指定玩家
    //
    // @param pPlayer 被踢出的玩家对象指针
    // @param eErrCode 错误码，用于指示踢出玩家的原因
    // @param sReason 可选的踢出玩家的详细原因说明，默认为空字符串
    // @return 返回操作结果，0表示成功，非0表示失败
    static int KickPlayer(NFPlayer* pPlayer, proto_ff::Proto_CS_ErrorCode eErrCode, const char* sReason = "");

    // @param pPlayer 要恢复的玩家对象指针
    // @param pSession 玩家的会话对象指针，用于重新建立会话
    // @return 返回操作结果，0表示成功，非0表示失败
    static int RestorePlayer(NFPlayer* pPlayer, NFSession* pSession);

public:
    /**
     * 玩家登录回调
     *
     * @param pPlayer 指向玩家对象的指针
     * @param iIsResume 是否恢复游戏的标志
     * @return 返回对登录事件处理的结果
     */
    static int OnPlayerLogin(NFPlayer* pPlayer, bool iIsResume);

    /**
     * 玩家注销回调
     *
     * @param pPlayer 指向玩家对象的指针
     * @return 返回对注销事件处理的结果
     */
    static int OnPlayerLogout(NFPlayer* pPlayer);

    // 当玩家断开连接时的回调函数
    // 参数 pPlayer: 玩家对象指针
    // 参数 iType: 断开连接的类型
    // 参数 iReason: 断开连接的原因
    // 返回值: 处理结果，0为成功
    static int OnPlayerDisconnect(NFPlayer* pPlayer, int iType, int iReason);


    // 当玩家恢复时的回调函数
    // 该函数在玩家数据被恢复时调用，允许进行一些初始化或者同步操作
    // 参数 pPlayer: 指向NFPlayer对象的指针，代表正在恢复的玩家
    // 返回值: 返回一个整数，通常用于表示操作的结果
    static int OnPlayerRestore(NFPlayer* pPlayer);

    // 当玩家完成恢复时的回调函数
    // 该函数在玩家数据已经完全恢复，且新的会话建立时调用，可以用于处理与会话相关的操作
    // 参数 pPlayer: 指向NFPlayer对象的指针，代表已经恢复的玩家
    // 参数 pOld: 指向前一个NFSession对象的指针，用于表示之前的会话
    // 参数 pNew: 指向新的NFSession对象的指针，用于表示当前的会话
    // 返回值: 返回一个整数，通常用于表示操作的结果
    static int OnPlayerRestored(NFPlayer* pPlayer, NFSession* pOld, NFSession* pNew);

public:
    /**
     * 根据平台类型、账户类型和OpenID计算账户UIN
     *
     * @param ePlatType 平台类型，参考proto_ff::Proto_PlatType定义
     * @param eAccoutType 账户类型，参考proto_ff::eAccountType定义
     * @param pszOpenID OpenID字符串，用于唯一标识用户
     *
     * @return 返回计算得到的账户UIN
     *
     * 此函数的目的是为了根据给定的平台类型、账户类型和OpenID计算出唯一的账户UIN，
     * 这在需要将不同平台或类型的账户映射到统一标识时非常有用。由于函数的具体实现
     * 涉及到账户信息的处理，因此被声明为static，以确保其操作的独立性和安全性。
     */
    static uint64_t CalcAccountUIN(proto_ff::Proto_PlatType ePlatType, proto_ff::eAccountType eAccoutType, const std::string& pszOpenID);

public:
    static int MakeRoleDetailForNew(proto_ff::tbRoleDetail* pRoleDetailOut, uint64_t ullRoleID, RoleOne& stRoleOne);
public:
    //exp
    static int AddExp(NFPlayer* pPlayer, uint64_t ullAddExp, int eReason, int iReasonParam, uint64_t* ullRealAdd = NULL);
    static bool IsExpFull(NFPlayer* pPlayer);
    static int ExpToMoney(NFPlayer* pPlayer, uint64_t uExp, int eReason);;
    static double CalcExpBonus(NFPlayer* pPlayer, double exp);
public:
    static int NotifyAttr(NFPlayer* pPlayer, bool bAll /*=false*/);
};
